package client_server.IO;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Observable;


/**
 * InputOutputDataThread handles all the communication between the client and the server on the client side.
 * @author Martin Nume
 *
 */
public class InputOutputDataThread extends Observable implements Runnable{
	private volatile Thread thread;
	private Socket socket;
	private BufferedReader in;
	private PrintWriter out;
	//buffer for outgoing data
	private ArrayList<String> writeBuffer;
	private final int THREAD_SLEEP = 40;
	
	public InputOutputDataThread(Socket socket) {
		this.socket = socket;
		writeBuffer = new ArrayList<String>();
		thread = new Thread(this);
		in = null;
		out=null;
	}
	/**
	 * Starts the thread
	 */
	public void startThread() {
		thread.start();
	}
	public void stopThread() {
		if(thread != null) {
			Thread temp = thread;
			thread = null;
			temp.interrupt();
		}
	}
	/**
	 * Outbuffer for the data waiting to be sent to the server.
	 * @param str the outgoing data
	 */
	public synchronized void addToOutBuffer(String str) {
		writeBuffer.add(str);
	}
	
	@Override
	public void run() {
		try {
			//instream
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			//outstream
			out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
			String text = "";
			try {
				while(Thread.currentThread() == thread) {
					try {
						Thread.sleep(THREAD_SLEEP);
					} catch (InterruptedException e) { e.printStackTrace();	}
					
					if(in.ready()) {
						//read from stream
						text = in.readLine();
						//notify observers that data has read
						setChanged();
						notifyObservers(text);
					}
					else if(writeBuffer.size() > 0){
						//write data from the outgoing buffer
						out.println(writeBuffer.remove(0));
						out.flush();
						
					}
				}
			}
			finally {
				if(in != null)
					in.close();
				if(out != null)
					out.close();
				if( socket!= null)
					socket.close();
			}
		} catch (IOException e) {
			System.out.println("Could not create datastream ");
			e.printStackTrace();
		}
	}
}
